/* * Copyright 2014-2016 Groupon, Inc * Copyright 2014-2016 The Billing Project, LLC * * The Billing Project licenses this file to you under the Apache License, version 2.0 * (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package org.killbill.billing.payment.logging; import java.util.ArrayList; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.regex.Pattern; import org.slf4j.event.SubstituteLoggingEvent; import org.slf4j.helpers.FormattingTuple; import org.slf4j.helpers.MessageFormatter; import org.slf4j.helpers.SubstituteLogger; import com.google.common.base.Optional; public class SpyLogger extends SubstituteLogger { private final List<LogMessage> logMessageList = new ArrayList<LogMessage>(); public SpyLogger(String loggerName) { super(loggerName, new LinkedBlockingQueue<SubstituteLoggingEvent>(), false); } public static final String LOG_LEVEL_TRACE = "TRACE"; public static final String LOG_LEVEL_DEBUG = "DEBUG"; public static final String LOG_LEVEL_INFO = "INFO"; public static final String LOG_LEVEL_WARN = "WARN"; public static final String LOG_LEVEL_ERROR = "ERROR"; @Override public String getName() { return super.getName(); } @Override public boolean isTraceEnabled() { return super.isTraceEnabled(); } @Override public void trace(final String msg) { super.trace(msg); save(LOG_LEVEL_TRACE, msg, null); } @Override public void trace(final String format, final Object arg) { super.trace(format, arg); formatAndSave(LOG_LEVEL_TRACE, format, arg, null); } @Override public void trace(final String format, final Object arg1, final Object arg2) { super.trace(format, arg1, arg2); formatAndSave(LOG_LEVEL_TRACE, format, arg1, arg2); } @Override public void trace(final String format, final Object... arguments) { super.trace(format, arguments); formatAndSave(LOG_LEVEL_TRACE, format, arguments); } @Override public void trace(final String msg, final Throwable t) { super.trace(msg, t); save(LOG_LEVEL_TRACE, msg, t); } @Override public boolean isDebugEnabled() { return super.isDebugEnabled(); } @Override public void debug(final String msg) { super.debug(msg); save(LOG_LEVEL_DEBUG, msg, null); } @Override public void debug(final String format, final Object arg) { super.debug(format, arg); formatAndSave(LOG_LEVEL_DEBUG, format, arg, null); } @Override public void debug(final String format, final Object arg1, final Object arg2) { super.debug(format, arg1, arg2); formatAndSave(LOG_LEVEL_DEBUG, format, arg1, arg2); } @Override public void debug(final String format, final Object... arguments) { super.debug(format, arguments); formatAndSave(LOG_LEVEL_DEBUG, format, arguments); } @Override public void debug(final String msg, final Throwable t) { super.debug(msg, t); save(LOG_LEVEL_DEBUG, msg, t); } @Override public boolean isInfoEnabled() { return super.isInfoEnabled(); } @Override public void info(final String msg) { super.info(msg); save(LOG_LEVEL_INFO, msg, null); } @Override public void info(final String format, final Object arg) { super.info(format, arg); formatAndSave(LOG_LEVEL_INFO, format, arg, null); } @Override public void info(final String format, final Object arg1, final Object arg2) { super.info(format, arg1, arg2); formatAndSave(LOG_LEVEL_INFO, format, arg1, arg2); } @Override public void info(final String format, final Object... arguments) { super.info(format, arguments); formatAndSave(LOG_LEVEL_INFO, format, arguments); } @Override public void info(final String msg, final Throwable t) { super.info(msg, t); save(LOG_LEVEL_INFO, msg, t); } @Override public boolean isWarnEnabled() { return super.isWarnEnabled(); } @Override public void warn(final String msg) { super.warn(msg); save(LOG_LEVEL_WARN, msg, null); } @Override public void warn(final String format, final Object arg) { super.warn(format, arg); formatAndSave(LOG_LEVEL_WARN, format, arg, null); } @Override public void warn(final String format, final Object... arguments) { super.warn(format, arguments); formatAndSave(LOG_LEVEL_WARN, format, arguments); } @Override public void warn(final String format, final Object arg1, final Object arg2) { super.warn(format, arg1, arg2); formatAndSave(LOG_LEVEL_WARN, format, arg1, arg2); } @Override public void warn(final String msg, final Throwable t) { super.warn(msg, t); save(LOG_LEVEL_WARN, msg, t); } @Override public boolean isErrorEnabled() { return super.isErrorEnabled(); } @Override public void error(final String msg) { super.error(msg); save(LOG_LEVEL_ERROR, msg, null); } @Override public void error(final String format, final Object arg) { super.error(format, arg); formatAndSave(LOG_LEVEL_ERROR, format, arg, null); } @Override public void error(final String format, final Object arg1, final Object arg2) { super.error(format, arg1, arg2); formatAndSave(LOG_LEVEL_ERROR, format, arg1, arg2); } @Override public void error(final String format, final Object... arguments) { super.error(format, arguments); formatAndSave(LOG_LEVEL_ERROR, format, arguments); } @Override public void error(final String msg, final Throwable t) { super.error(msg, t); save(LOG_LEVEL_ERROR, msg, t); } /** * Returns a list with the stored log messages * * @return a list with the stored log messages */ public List<LogMessage> getLogMessageList() { return logMessageList; } /** * Checks if a certain message has been logged. It has to fulfil the * given regex pattern. If a logLevel is provided, the expected message * also has to have this log level. If no log level has been provided, * a message is just compared to the regex pattern. * * @param regex pattern that the message should follow. * @param logLevel log level that the message should have. * @return true if a message has been found, false if no has been found */ public boolean contains(String regex, Optional<String> logLevel) { Pattern pattern = Pattern.compile(regex); for (LogMessage logMessage : logMessageList) { final boolean messageMatches = pattern.matcher(logMessage.message).find(); final boolean logLevelMatches = logLevel.isPresent() ? logLevel.get().equals(logMessage.logLevel) : true; if (messageMatches && logLevelMatches) { return true; } } return false; } private void formatAndSave(String logLevel, String format, Object arg1, Object arg2) { FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); save(logLevel, tp.getMessage(), tp.getThrowable()); } private void formatAndSave(String logLevel, String format, Object... arguments) { FormattingTuple tp = MessageFormatter.arrayFormat(format, arguments); save(logLevel, tp.getMessage(), tp.getThrowable()); } private void save(String logLevel, String message, Throwable t) { logMessageList.add(new LogMessage(logLevel, message, t)); } public class LogMessage { public final String logLevel; public final String message; public final Throwable throwable; public LogMessage(final String logLevel, final String message, final Throwable throwable) { this.logLevel = logLevel; this.message = message; this.throwable = throwable; } } }